//{=================================================================================
//! @file    SquareSolver.cpp
//! @date    2014-09-18 17:23
//! @author  Dima Samchenko <samchenko.da@gmail.com>, 471 group
//!
//! Solution of quadratic equation with analysis of particular cases.
//!
//! @par     The problem
//!          Program input 3 coefficients of quadratic equation. Need to output
//!          number of roots (-1 in case of infinite number) and these roots.
//!
//}=================================================================================
//--------------------------------------------------------------------------



#include <stdio.h>
#include <math.h>
#include <float.h>
#include <assert.h>
#include <stdlib.h>

#define IsZero(x) (fabs(x) < DBL_EPSILON) //! Check x = 0
#define IsAboveZero(x) (x > DBL_EPSILON) //! Check x > 0


//--------------------------------------------------------------------------
// #define MY_COMP
//--------------------------------------------------------------------------
#ifdef MY_COMP
    #define OUT printf("#"), //! debug output
#else
    #define OUT if(0) //! normal output
#endif // MY_COMP
//--------------------------------------------------------------------------


//--------------------------------------------------------------------------
// #define ASSERT
//--------------------------------------------------------------------------
#ifndef NDEBUG
    #define ASSERT(cond)  if(!(cond))\
                          {\
                              printf("FAIL: %s, in %s, %d, %s\n",\
                              #cond, __FILE__, __LINE__, __PRETTY_FUNCTION__);\
                              abort();\
                          }
#else
    #define ;
#endif

//! The value returned SolveSquare an infinitely large number of roots.
int const INFINITE_ROOTS = -1;

/** ********************************************************************************
 SolveSquare - solve a square or linear equation specified by its coefficients.

 @param      a   Equation a-coefficient
 @param      b   Equation b-coefficient
 @param      c   Equation c-coefficient
 @param[out] x1  1st root of equation, if exist (if not, value will be unchanged)
 @param[out] x2  2nd root of equation, if exist (if not, value will be unchanged)

 @return         Number of roots or zero if none, -1 if infinite number of roots

************************************************************************************/

int SolveSquare(double a, double b, double c,
                double* x1, double* x2);

int main()
{
double a = 0, b = 0, c = 0; //! Coefficients of equation


OUT printf(__DATE__ " " __TIME__ "\n"); //! Date and time of the latest compiling
OUT printf("Written by Dima\n");
OUT printf("Enter coefficients: a b c > ");


if (scanf("%lg %lg %lg", &a, &b, &c) != 3)
    return OUT printf("ERROR: Bad input. Example: 1 2 -4\n"), 1;

double x1 = 0, x2 = 0; //! Roots of equation

int nRoots = SolveSquare(a, b, c, &x1, &x2);
ASSERT(x1*x2 == c && x1 + x2 == -b);

switch (nRoots)
    {
    case INFINITE_ROOTS:
        printf("-1\n");
        OUT printf("Any root is solution of this quadratic equation\n");
        break;
    case 0:
        printf("0\n");
        OUT printf("Quadratic equation has no roots\n");
        break;
    case 1:
        OUT printf("Quadratic equation has roots:\n");
        printf("%d\n", nRoots);
        OUT printf("Its value:\n");
        printf("%lg\n", x1);
        break;
    case 2:
        OUT printf("Quadratic equation has roots:\n");
        printf("%d\n",nRoots);
        OUT printf("Their values:\n");
        printf("%lg, %lg\n", x1, x2);
        break;
    default:
        return OUT printf("Sorry< something went wrong...\n"), 1;
    }

return 0;
}

int SolveSquare(double a, double b, double c,
                double* x1, double* x2)
{
if ( IsZero(a) )
    {
    if ( IsZero(b) )
        if ( IsZero(c) ) return INFINITE_ROOTS;
        else return 0;
    else // b != 0, bx + c = 0, x = -c/b
        {
        if ( IsZero(c) ) *x1 = 0;
        else        *x1 = -c/b;
        return 1;
        }
    }
else // a != 0
    {
    double d = b*b - 4*a*c;

    if ( IsZero(d) || IsAboveZero(d) )
        {
        if ( IsAboveZero(d) )
            {
            d = sqrt(d);
            *x1 = (-b - d) / 2/a;
            *x2 = (-b + d) / 2/a;
            return 2;
            }
        else
            {
            if ( IsZero(b) ) *x1 = 0;
            else        *x1 = -b / 2/a;
            return 1;
            }
        }
    else
        return 0;
    }
}
